package com.my.bigsite.modules.act.util;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.activiti.bpmn.model.BpmnModel;
import org.activiti.bpmn.model.EndEvent;
import org.activiti.bpmn.model.ExclusiveGateway;
import org.activiti.bpmn.model.FlowElement;
import org.activiti.bpmn.model.FlowNode;
import org.activiti.bpmn.model.GraphicInfo;
import org.activiti.bpmn.model.SequenceFlow;
import org.activiti.bpmn.model.StartEvent;
import org.activiti.bpmn.model.UserTask;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.impl.cmd.GetBpmnModelCmd;
import org.springframework.beans.factory.annotation.Autowired;

import com.my.bigsite.common.activiti.support.EdgeDTO;
import com.my.bigsite.common.activiti.support.NodeDTO;

/**
 * bpmn文件解析.
 * @author Administrator
 *
 */
public class BpmnUtil {


	/**
	 * 获取流程定义文件所有的节点信息. 建议在部署流程的时候 讲节点解析并保存数据库，以便后续的跳转设置。
	 * 
	 */
	public static List<NodeDTO> getNodeByProcess(String procInsId,ProcessEngine processEngine) {
		// 查询流程下的所有节点
		GetBpmnModelCmd getBpmnModelCmd = new GetBpmnModelCmd(procInsId);
		BpmnModel bpmnModel = processEngine.getManagementService()
				.executeCommand(getBpmnModelCmd);

		Map<String, GraphicInfo> graphicInfoMap = bpmnModel.getLocationMap();

		List<NodeDTO> nodeDtos = new ArrayList<NodeDTO>();

		// 循环查询流程定义下的节点
		for (Map.Entry<String, GraphicInfo> entry : graphicInfoMap.entrySet()) {
			String key = entry.getKey();//获取节点id
			GraphicInfo graphicInfo = entry.getValue();
			if (!(bpmnModel.getFlowElement(key) instanceof ExclusiveGateway)) {
				nodeDtos.add(convertNodeDto(graphicInfo,
						bpmnModel.getFlowElement(key), key, bpmnModel));
			}

		}
		return nodeDtos;
	}

	/**
	 * 读取bpmn文件元素，并转换.
	 * 
	 * @param graphicInfo  图形信息: 长度，宽度，元素坐标等信息.
	 * @param flowElement  流程元素:节点的配置信息。如 :form元素，监听器配置，OutgoingFlows.
	 * @param id           元素Id
	 * @param bpmnModel     
	 * @return
	 */
	public static NodeDTO convertNodeDto(GraphicInfo graphicInfo,
			FlowElement flowElement, String id, BpmnModel bpmnModel) {
		NodeDTO nodeDto = new NodeDTO();
		nodeDto.setX((int) graphicInfo.getX());
		nodeDto.setY((int) graphicInfo.getY());
		nodeDto.setWidth((int) graphicInfo.getWidth());
		nodeDto.setHeight((int) graphicInfo.getHeight());
		nodeDto.setId(id);
		nodeDto.setName(flowElement.getName());

		if (flowElement instanceof UserTask) {
			nodeDto.setType("用户任务");
			UserTask userTask = (UserTask) flowElement;
			nodeDto.setAssignee(userTask.getAssignee());
		} else if (flowElement instanceof StartEvent) {
			nodeDto.setType("开始事件");
		} else if (flowElement instanceof EndEvent) {
			nodeDto.setType("结束事件");
		}
		if (flowElement instanceof FlowNode) { //StartEvent继承Event,Event继承FlowNode
			FlowNode flowNode = (FlowNode) flowElement;
			//获取连接当前节点之后的所有连线（下一节点连线)
			for (SequenceFlow sequenceFlow : flowNode.getOutgoingFlows()) {
				EdgeDTO edgeDto = new EdgeDTO();
				edgeDto.setId(sequenceFlow.getTargetRef());
				for (GraphicInfo flowGraphicInfo : bpmnModel
						.getFlowLocationGraphicInfo(sequenceFlow.getId())) {
					List<Integer> position = new ArrayList<Integer>();
					position.add((int) flowGraphicInfo.getX()
							- ((int) graphicInfo.getWidth() / 2));
					position.add((int) flowGraphicInfo.getY()
							- ((int) graphicInfo.getHeight() / 2));
					edgeDto.getG().add(position);
				}
				edgeDto.getG().remove(0);
				edgeDto.getG().remove(edgeDto.getG().size() - 1);
				nodeDto.getOutgoings().add(edgeDto);//设置当前节点的下一节点
			}
		}
		return nodeDto;
	}

}
